package com.bjsxt.base.lockDesign.design2;

import java.util.concurrent.atomic.AtomicReference;

/**
 * 自旋锁--可重入版
 */
public class SpinReLock {
    private AtomicReference<Thread> owner = new AtomicReference<>();
    private int count = 0; // // 可重入锁都必须有个count变量

    public void lock() {
        Thread current = Thread.currentThread();
        // 第一次lock时owner的value为null, 所以会绕过if
        // 第二次lock时如果是当前线程则直接return, 防止进入自旋代码块; 是其他线程就进入自旋代码块
        if (current == owner.get()) {
            count++;
            return;
        }
        // 不停尝试获取锁, 故称为自旋锁
        // 第一次lock时owner里面的value为null, 所以不会进入while死循环中
        while (!owner.compareAndSet(null, current)) {
            // 自旋空转
            // 自旋区别于wait: 自旋不会让出cpu而是一直空转, wait会让出cpu; 空转虽然耗cpu但是避免是上下文切换
        }
    }

    public void unlock() {
        Thread current = Thread.currentThread();
        if (current == owner.get()) {
            if (count != 0) {
                // 须把锁解干净
                count--;
            } else {
                owner.compareAndSet(current, null);
            }
        }

    }
}
